using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace PageDraw
{
    public partial class DrawArea : PictureBox
    {
        private GraphicsTree graphicsTree;

        public GraphicsTree GraphicsTree
        {
            get { return graphicsTree; }
        }

        private FormMain formMain;
        private TextBox hideTB;
        private GraphicsTreeMgr graphicsTreeMgr;
        private Font coorFont;

        public GraphicsTreeMgr GraphicsTreeMgr
        {
            get { return graphicsTreeMgr; }
        }

        public FormMain FormMain
        {
            set { formMain = value; }
        }

        public DrawArea()
        {
            InitializeComponent();
            SetStyle(ControlStyles.AllPaintingInWmPaint |
                ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
            graphicsTree = new GraphicsTree();
            graphicsTreeMgr = new GraphicsTreeMgr(graphicsTree, this);
            coorFont = new Font(this.Font.FontFamily, 8F, FontStyle.Regular);

            hideTB = new TextBox();
            this.Controls.Add(hideTB);
            hideTB.Width = 0;
            hideTB.KeyDown += new KeyEventHandler(hideTB_KeyDown);
        }

        private void hideTB_KeyDown(object sender, KeyEventArgs e)
        {
            hideTB.Clear();
            if (e.KeyCode == Keys.Delete)
            {
                graphicsTreeMgr.DeleteSelectedDrawObjects();
                this.Refresh();
            }
            int dx = 0;
            int dy = 0;
            if (e.KeyCode == Keys.Left)
            {
                dx = -1;
            }
            else if (e.KeyCode == Keys.Right)
            {
                dx = 1;
            }
            else if (e.KeyCode == Keys.Up)
            {
                dy = -1;
            }
            else if (e.KeyCode == Keys.Down)
            {
                dy = 1;
            }
            if (dx != 0 || dy != 0)
            {
                graphicsTreeMgr.ResetSelectedDrawObjectL(dx, dy);
                this.Refresh();
            }
        }

        private ToolObject drawTool;

        public ToolObject DrawTool
        {
            set { drawTool = value; }
        }

        private void DrawArea_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (drawTool != null && e.Button == MouseButtons.Left)
            {
                drawTool.MouseDoubleClick(sender as DrawArea, e);
            }
            else
            {
                if (!graphicsTreeMgr.AddEvent(e.Location))
                {
                    formMain.ResizeDrawArea();
                }
            }
        }

        private bool isBtnDown = false;
        private Point mouseDownLocation;
        private bool isCtrlDown = false;

        private void DrawArea_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.isBtnDown = true;
                this.mouseDownLocation = e.Location;
                if (drawTool != null)
                {
                    graphicsTreeMgr.ClearSelectedDrawObject();
                    drawTool.MouseDown(sender as DrawArea, e);
                    this.Refresh();
                    formMain.setTitle("PageDraw *");
                }
                else
                {
                    if (this.Cursor != Cursors.SizeAll)
                    {
                        this.isCtrlDown = (Control.ModifierKeys == Keys.Control);
                        if (graphicsTreeMgr.SetDrawObjectSelection(e.Location, isCtrlDown))
                        {
                            this.Cursor = Cursors.Hand;
                        }
                        else 
                        {
                            sectionRect.Location = e.Location;
                        }
                        this.Refresh();
                    }
                }
            }
            //else if (e.Button == MouseButtons.Right)
            //{
            //    graphicsTreeMgr.SetSingleSelection(e.Location);
            //}
        }

        private Rectangle sectionRect = Rectangle.Empty;
        private bool isDrawCross;

        public bool IsDrawCross
        {
            get { return isDrawCross; }
            set { isDrawCross = value; }
        }

        private Point mouseMoveLoc;

        private void DrawArea_MouseMove(object sender, MouseEventArgs e)
        {
            this.formMain.setMouseLocation(e.Location);
            if (this.IsDrawCross)
            {
                mouseMoveLoc = e.Location;
                this.Refresh();
            }
            if (e.Button == MouseButtons.Left)
            {
                if (isBtnDown)
                {
                    if (drawTool != null)
                    {
                        drawTool.MouseMove(sender as DrawArea, e);
                    }
                    else
                    {
                        if (this.Cursor == Cursors.SizeAll)
                        {
                            graphicsTreeMgr.ResetSelectedDrawObjectLorS(mouseDownLocation, e.Location);
                            this.Refresh();
                            formMain.setTitle("PageDraw *");
                        }
                        else if (this.Cursor == Cursors.Hand)
                        {
                            int dx = e.X - mouseDownLocation.X;
                            int dy = e.Y - mouseDownLocation.Y;
                            mouseDownLocation.X = e.X;
                            mouseDownLocation.Y = e.Y;
                            graphicsTreeMgr.ResetSelectedDrawObjectL(dx, dy);
                            this.Refresh();
                            formMain.setTitle("PageDraw *");
                        }
                        else
                        {
                            SetSectionRect(e.Location);
                            this.Refresh();
                        }
                    }
                }
            }
            else
            {
                if (drawTool == null)
                {
                    bool val = graphicsTreeMgr.IsPointOnHandle(e.Location);
                    if (val)
                    {
                        this.Cursor = Cursors.SizeAll;
                    }
                    else
                    {
                        this.Cursor = Cursors.Default;
                    }
                }
            }
        }

        private void SetSectionRect(Point point)
        {
            if (point.X > mouseDownLocation.X)
            {
                if (point.Y > mouseDownLocation.Y)
                {
                    sectionRect.Width = point.X - sectionRect.X;
                    sectionRect.Height = point.Y - sectionRect.Y;
                }
                else
                {
                    sectionRect.Width = point.X - mouseDownLocation.X;
                    sectionRect.Height = mouseDownLocation.Y - point.Y;
                    sectionRect.Y = point.Y;
                }
            }
            else
            {
                if (point.Y > mouseDownLocation.Y)
                {
                    sectionRect.Width = mouseDownLocation.X - point.X;
                    sectionRect.Height = point.Y - mouseDownLocation.Y;
                    sectionRect.X = point.X;
                }
                else
                {
                    sectionRect.Width = mouseDownLocation.X - point.X;
                    sectionRect.Height = mouseDownLocation.Y - point.Y;
                    sectionRect.X = point.X;
                    sectionRect.Y = point.Y;
                }
            }
        }

        private void DrawArea_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.isBtnDown = false;
                if (drawTool != null)
                {   
                    drawTool.MouseUp(sender as DrawArea, e);
                    formMain.ResetDrawTool();
                }
                else
                {
                    if (!sectionRect.IsEmpty)
                    {
                        graphicsTreeMgr.MultiSeletecedDrawObject(sectionRect);
                    }
                    this.sectionRect = Rectangle.Empty;
                    this.Refresh();
                }
            }
        }

        private bool isMouseEnter;

        private void DrawArea_MouseEnter(object sender, System.EventArgs e)
        {
            this.hideTB.Focus();
            this.isMouseEnter = true;
        }

        private void DrawArea_MouseLeave(object sender, System.EventArgs e)
        {
            this.isMouseEnter = false;
            this.formMain.setMouseLocation(Point.Empty);
            this.Refresh();
        }

        private void DrawArea_Paint(object sender, PaintEventArgs e)
        {
            using (Image canvas = new Bitmap(this.Width, this.Height))
            {
                using (Graphics g = Graphics.FromImage(canvas))
                {
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    //g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                    // clear the background
                    g.Clear(Color.White);
                    // draw coordinate
                    DrawCoordinate(g);
                    // draw controls
                    graphicsTree.Draw(sender as DrawArea, g);
                    // draw cross
                    DrawCross(g);
                    // selection region
                    ControlPaint.DrawFocusRectangle(g, sectionRect, Color.Black, Color.Transparent);
                    //g.DrawRectangle(Pens.Black, sectionRect);
                    // draw the canvas to the drawArea
                    e.Graphics.DrawImage(canvas, 0, 0);
                }
            }
        }

        private void DrawCross(Graphics g)
        {
            if(this.IsDrawCross && this.isMouseEnter)
            {
                Point xsp = new Point(0, mouseMoveLoc.Y);
                Point xep = new Point(2000, mouseMoveLoc.Y);
                Point ysp = new Point(mouseMoveLoc.X, 0);
                Point yep = new Point(mouseMoveLoc.X, 1000);
                g.DrawLine(Pens.Chocolate, xsp, xep);
                g.DrawLine(Pens.Chocolate, ysp, yep);
            }
        }

        private bool isDrawCoordinate;

        public bool IsDrawCoordinate
        {
            get { return isDrawCoordinate; }
            set { isDrawCoordinate = value; }
        }

        private void DrawCoordinate(Graphics g)
        {
            if (isDrawCoordinate)
            {
                Point o = new Point(0, 0);
                Point xe = new Point(2000, 0);
                Point ye = new Point(1000, 0);
                Point sxp = new Point();
                Point exp = new Point();
                Point syp = new Point();
                Point eyp = new Point();
                for (int i = 0; i < 2000; i++)
                {
                    sxp.X = i;
                    sxp.Y = 0;
                    exp.X = i;
                    syp.X = 0;
                    syp.Y = i;
                    eyp.Y = i;
                    if (i % 5 == 0 && i != 0)
                    {
                        exp.Y = 2;
                        eyp.X = 2;
                        if (i % 50 == 0)
                        {
                            exp.Y = 5;
                            eyp.X = 5;
                            g.DrawString(i.ToString(), coorFont, Brushes.Black, exp);
                            g.DrawString(i.ToString(), coorFont, Brushes.Black, eyp);
                        }
                        g.DrawLine(Pens.Black, sxp, exp);
                        g.DrawLine(Pens.Black, syp, eyp);
                    }
                    
                }
            }
        }

        public void AddDrawObject(DrawObject drawObject)
        {
            graphicsTree.AddDrawObject(drawObject);
        }

        public void AlignHandle(Align align)
        {
            graphicsTreeMgr.AlignHandle(align);
        }

        public void MoveObjects(Align align)
        {
            int dx = 0;
            int dy = 0;
            if (align == Align.Left)
            {
                dx = -1;
            }
            else if (align == Align.Right)
            {
                dx = 1;
            }
            else if (align == Align.UP)
            {
                dy = -1;
            }
            else if (align == Align.Down)
            {
                dy = 1;
            }
            if (dx != 0 || dy != 0)
            {
                graphicsTreeMgr.ResetSelectedDrawObjectL(dx, dy);
                this.Refresh();
            }
        }

        public void SetPropGridSelectedObject(Object drawObject)
        {
            formMain.SetPropGridSelectedObject(drawObject);
        }
    }
}
